package jesss.commands;

import com.amazonaws.AmazonClientException;
import com.amazonaws.services.s3.model.PutObjectRequest;
import com.amazonaws.services.s3.model.PutObjectResult;
import jesss.options.ExtendedGnuParser;
import jesss.options.JesssOptions;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;

import org.apache.commons.cli.MissingArgumentException;
import org.apache.commons.cli.Options;

import java.io.File;

/**
 * User: Lee
 * Date: 8/23/13
 * Time: 3:24 PM
 */
public class PutObjectCommand<T> extends AbstractJesssCommand {

    private JesssOptions jesssOptions = null;
    private Options options = new Options();
    private String bucketName;
    private String key;
    private String sourceFilePath;

    /**
     * Constructs a new {@link PutObjectCommand} object to
     * upload files to an S3 location.
     *
     * @param jesssOptions
     */
    public PutObjectCommand(JesssOptions jesssOptions) throws Exception {
        this.jesssOptions = jesssOptions;
        setOptions();
        try {
            parseArgs(jesssOptions.getArgs());
        } catch (Exception e) {
            printUsage();
            throw e;
        }
    }

    @Override
    public CommandResult<PutObjectResult> executeCommand() {
        CommandResult<PutObjectResult> commandResult = new CommandResult<>();

        try {
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, key, new File(sourceFilePath));
            PutObjectResult putObjectResult = jesssOptions.getAmazonS3().putObject(putObjectRequest);

            if (putObjectResult != null) {
                displayMessage(
                        String.format("PutObjectResult: ETag=%s\tExpirationTime=%s\tVersionID=%s\tMD5=%s}",
                        putObjectResult.getETag(),
                        putObjectResult.getExpirationTime(),
                        putObjectResult.getVersionId(),
                        putObjectResult.getContentMd5()));
            }

            commandResult.setResultStatus(ResultStatus.Success);
            commandResult.setResultValue(putObjectResult);
        } catch (AmazonClientException e) {
            commandResult.setResultStatus(ResultStatus.Error);
            commandResult.setStatusMessage("Unable to put object.");
        }
        return commandResult;
    }


    private void setOptions() {
        options = new Options();
        options.addOption("bn", "bucketName", true, "Bucket name to list objects from");
        options.addOption("k", "key", true, "Key");
        options.addOption("sf", "sourceFile", true, "Source file");
    }

    private void parseArgs(String[] args) throws Exception {
        if (args == null || args.length == 0) {
            printUsage();
        }

        try {
            CommandLineParser parser = new ExtendedGnuParser(true);
            CommandLine cmd = parser.parse(options, args);

            if (cmd.hasOption("bn")) {
                bucketName = cmd.getOptionValue("bn");
            } else {
                throw new MissingArgumentException("Missing bucket name parameter.");
            }

            if (cmd.hasOption("k")) {
                key = cmd.getOptionValue("k");
            } else {
                throw new MissingArgumentException("Missing key parameter.");
            }

            if (cmd.hasOption("sf")) {
                sourceFilePath = cmd.getOptionValue("sf");
                if (!new File(sourceFilePath).exists()) {
                    throw new IllegalArgumentException(String.format("The source file \"%s\" doesn't exist.", sourceFilePath));
                }
            } else {
                throw new MissingArgumentException("Missing source file path parameter.");
            }
        } catch (Exception e) {
            printUsage();
            throw e;
        }
    }

    private void printUsage() {
        System.out.println("Usage:");
        System.out.println("jesss.jesss -cn putObject -bn <mybucket> -k <key> -sf <source file name>");
    }
}
